if (globalThis.platform == "nodejs") {
    const fs = require('fs');
    const path = require("path");

    var _O_RDONLY = 0x0000
    var _O_WRONLY = 0x0001
    var _O_RDWR = 0x0002
    var _O_APPEND = 0x0008
    var _O_CREAT = 0x0100
    var _O_TRUNC = 0x0200
    var _O_EXCL = 0x0400
    var _O_TEXT = 0x4000
    var _O_BINARY = 0x8000
    var _O_WTEXT = 0x10000
    var _O_U16TEXT = 0x20000
    var _O_U8TEXT = 0x40000
    var _O_ACCMODE = (_O_RDONLY|_O_WRONLY|_O_RDWR)

    var _O_RAW = _O_BINARY
    var _O_NOINHERIT = 0x0080
    var _O_TEMPORARY = 0x0040
    var _O_SHORT_LIVED = 0x1000

    var _O_SEQUENTIAL = 0x0020
    var _O_RANDOM = 0x0010

    var O_RDONLY = _O_RDONLY
    var O_WRONLY = _O_WRONLY
    var O_RDWR = _O_RDWR
    var O_APPEND = _O_APPEND
    var O_CREAT = _O_CREAT
    var O_TRUNC = _O_TRUNC
    var O_EXCL = _O_EXCL
    var O_TEXT = _O_TEXT
    var O_BINARY = _O_BINARY
    var O_RAW = _O_BINARY
    var O_TEMPORARY = _O_TEMPORARY
    var O_NOINHERIT = _O_NOINHERIT
    var O_SEQUENTIAL = _O_SEQUENTIAL
    var O_RANDOM = _O_RANDOM
    var O_ACCMODE = _O_ACCMODE

    function checkPath(p) {
        return path.resolve(p);
    }

    function get_file_mode(flag) {
        switch (flag) {
            case O_RDONLY: return 'r';
            // case 'sr': return O_RDONLY | O_SYNC;
            case (O_RDONLY | O_BINARY): return "r";
            case O_RDWR: return 'r+';
            case (O_RDWR | O_BINARY): return 'r+';
            // case 'sr+': return O_RDWR | O_SYNC;
            case (O_TRUNC | O_CREAT | O_WRONLY): return 'w';
            case (O_TRUNC | O_CREAT | O_WRONLY | O_BINARY): return 'w';
            case (O_TRUNC | O_CREAT | O_WRONLY | O_EXCL): return 'wx';
            case (O_TRUNC | O_CREAT | O_RDWR): return 'w+';
            case (O_TRUNC | O_CREAT | O_RDWR | O_BINARY): return 'w+';
            case (O_TRUNC | O_CREAT | O_RDWR | O_EXCL): return 'wx+';
            case (O_APPEND | O_CREAT | O_WRONLY): return 'a';
            case (O_APPEND | O_CREAT | O_WRONLY | O_BINARY): return 'a';
            case (O_APPEND | O_CREAT | O_WRONLY | O_EXCL): return 'ax';
            case (O_APPEND | O_CREAT | O_RDWR): return 'a+';
            case (O_APPEND | O_CREAT | O_RDWR | O_EXCL):return 'ax+';
        }
    }

    module.exports = {
        /******* 
         * @description: 打开文件 nodejs请参考：http://nodejs.cn/api-v14/fs.html#fs_file_system_flags
         * @param {String} filePath 文件路径
         * @param {String} mode 打开模式：read ->[a] / write ->[w] / append ->[a] / binary->[b] / text->[t]
         * @return {Integer}
         * @author: null
         */
        open: function (filePath, flags) {
            filePath = checkPath(filePath);
            return fs.openSync(filePath, get_file_mode(flags));
        },
        /******* 
         * @description: 根据偏移获取文件内容
         * @param {Integer} fd 文件句柄
         * @param {Integer} position 偏移位置
         * @param {Integer} flag 打开方式
         * @return {Integer}
         * @author: null
         */        
        lseek: function(fd, position, flag) { // flag: 1/SEEK_CUR 2/SEEK_END 0/SEEK_SET
            var result = -1;

            const size = fs.fstatSync(fd, { bigint: false }).size;
            var buffer = Buffer.alloc(size);

            if (flag == 1) {
                var length = 0;
                result = fs.readSync(fd, buffer, 0, length, position);
            } else if(flag == 2) {
                var length = size;
                position = 0;
                result = fs.readSync(fd, buffer, 0, length, position);
            } else if(flag == 0) {
                var length = size - position;
                result = fs.readSync(fd, buffer, 0, length, position);
            } else {
                throw new Error("invaild flag");
            }
            return result;
        },
        /******* 
         * @description: 判断文件是否存在
         * @param {String} path
         * @param {String} mode
         * @return {Boolean}
         * @author: null
         */        
        access: function(path, mode) {
            var result = false;
            try {
                fs.accessSync(path, constants.R_OK | constants.W_OK);
                result = true;
            } catch (err) {
                result = false;
                console.error('no access!');
            }
            return result;
        },
        /******* 
         * @description: 获取文件大小
         * @param {Integer} fd
         * @return {Integer}
         * @author: null
         */        
        size: function (fd) {
            var size = -1;
            size = fs.fstatSync(fd, { bigint: false }).size;
            return size;
        },
        /******* 
         * @description: 关闭文件
         * @param {<FileHandle>} filehandle http://nodejs.cn/api-v14/fs.html#class-filehandle
         * @return {undefined}
         * @author: null
         */        
        close: function (fd) {
            fs.closeSync(fd);
            return undefined;
        },
        /******* 
         * @description: 判断传入的路径是否存在
         * @param {String} filePath
         * @return {Boolean}
         * @author: null
         */        
        exists: function (filePath) {
            var result = false;
            filePath = checkPath(filePath);
            try {
                result = fs.accessSync(filePath, fs.constants.R_OK | fs.constants.W_OK);
                result = true;
            } catch (err) {
                result = false;
                // console.error('no access!');
            }
            // var result = fs.accessSync(filePath);
            // var reult = fs.statSync(filePath);
            return result ? 1: -1;
        },
        /******* 
         * @description: 将文件从 oldPath 重命名为 newPath
         * @param {String} oldPath
         * @param {String} newPath
         * @return {*}
         * @author: null
         */        
        rename: function (oldPath, newPath) {
            return fs.renameSync(oldPath, newPath);
        },
        /******* 
         * @description: 删除文件或者目录 http://nodejs.cn/api-v14/fs.html#fsrmdirsyncpath-options
         * @param {String} filePath
         * @return {undefined}
         * @author: null
         */        
        remove: function (filePath) {
            return fs.rmSync(filePath, { force: false, maxRetries: 3, recursive: true, retryDelay: 200 })
        },
        /******* 
         * @description: 读文件
         * @param {Integer} fd
         * @param {Buffer | String} buffer
         * @param {Integer} size
         * @return {undefined}
         * @author: null
         */        
        read: function (fd, buffer, size) {
            return fs.readSync(fd, buffer, { offset: 0, length: size, position: 0 });
        },
        /******* 
         * @description: 写文件
         * @param {Integer} fd
         * @param {Buffer | String} buffer
         * @param {Integer} size
         * @return {*}
         * @author: null
         */        
        write: function (fd, buffers, size) {
            return fs.writeSync(fd, buffers, 0, size, 0);
        },
        /******* 
         * @description: 获取虚拟机当前执行路径
         * @param {*}
         * @return {String}
         * @author: null
         */        
        getcwd: function() {
            return process.cwd();
        },
        /******* 
         * @description: 修改虚拟机获取脚本路径
         * @param {String} path
         * @return {*}
         * @author: null
         */        
        chdir: function(path) {
            // todo nothing
            return path
        }
    };
}
